package com.suray.wcs.service.core.path.api.impl;

import com.suray.basic.wcs.path.core.Node;
import com.suray.basic.wcs.utils.LoggerUtil;
import com.suray.basic.wcs.utils.ModuleType;
import com.suray.commin.core.utils.SpringContextHolder;
import com.suray.system.run.util.PortFuncUtil;
import com.suray.system.run.util.PortTaskContainer;
import com.suray.wcs.service.enums.PortModel;
import com.suray.wcs.service.enums.TaskType;
import com.suray.wcs.service.system.bo.ConnectNodeBO;
import com.suray.wcs.service.system.entity.NodeDB;
import com.suray.wcs.service.system.entity.PortDB;
import com.suray.wcs.service.system.entity.PortTaskConfigDB;
import com.suray.wcs.service.system.entity.TaskDB;
import com.suray.wcs.service.system.service.impl.*;
import com.suray.wcs.service.test.base.BaseThread;
import com.suray.wcs.service.util.WcsUtil;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * 分配任务库口
 */
public class TaskPortAssignImpl extends BaseThread {

    private TaskDBServiceImpl taskDBService = SpringContextHolder.getBean(TaskDBServiceImpl.class);
    private PortDBServiceImpl portDBService = SpringContextHolder.getBean(PortDBServiceImpl.class);
    private NodeDBServiceImpl nodeDBService = SpringContextHolder.getBean(NodeDBServiceImpl.class);
    private ConnectConfServiceImpl connectConfService = SpringContextHolder.getBean(ConnectConfServiceImpl.class);
    private PortTaskConfigDBServiceImpl portTaskConfigDBService
            = SpringContextHolder.getBean(PortTaskConfigDBServiceImpl.class);

    public TaskPortAssignImpl() {
        super("选择出库口", 1000, ModuleType.WCS_SYSTEM);
    }

    @Override
    protected void process() {
        List<TaskDB> taskDBS = taskDBService.getNoEndNodeTask();
        List<PortTaskConfigDB> configDBS = portTaskConfigDBService.list();
        PortTaskContainer container = PortFuncUtil.analyzeOutPortTaskNum(taskDBService.findAllUnFinishTask(TaskType.OUT));

        for (TaskDB taskDB : taskDBS) {
            List<PortContainer> portContainers = PortFuncUtil.analyzePortContainer(taskDB, container, false);
            for (PortContainer portContainer : portContainers) {
                PortDB portDB = portContainer.getPortDB();
                NodeDB endNodeDB = null;
                try {
                    endNodeDB = WcsUtil.getRgvEndNode(taskDB.selectStartNode(), portDB, taskDB.getTaskType(),
                            nodeDBService);
                } catch (Exception e) {
                    LoggerUtil.warn("未找到合适的终点，库口：" + portDB.getPortName() + ", 任务：" + taskDB.getTaskId(),
                            this.getClass());
                }
                ConnectNodeBO endPlanBO = null;
                if (endNodeDB == null) {
                    NodeDB startNodeDB = new NodeDB();
                    Node startNode = taskDB.selectStartNode();
                    startNodeDB.setGridx(startNode.getX());
                    startNodeDB.setGridy(startNode.getY());
                    startNodeDB.setGridz(startNode.getZ());
                    endPlanBO = WcsUtil.getConnectNodeInOrOut(null, portDB.getPortCode(),
                            startNodeDB, null, TaskType.OUT.getTypeNum(), nodeDBService, connectConfService);

                    if (endPlanBO != null) {
                        endNodeDB = endPlanBO.getNodedb();
                    }
                }
                if (endNodeDB != null) {
                    Node startNode = generalPreTask(taskDB, endPlanBO);
                    int taskLayer = taskDB.selectStartNode().getZ();
                    if (startNode != null) {
                        taskLayer = startNode.getZ();
                    }
                    if (!PortFuncUtil.checkPortTaskConfig(portContainer, configDBS, taskLayer)) {
                        continue;
                    }
                    improveTask(taskDB, endNodeDB, portDB, startNode);
                    break;
                }
            }
        }
    }

    /**
     * 生成前置任务
     * @param taskDB
     * @param endPlanBO
     * @return
     */
    private Node generalPreTask(TaskDB taskDB, ConnectNodeBO endPlanBO) {
        if (endPlanBO == null || endPlanBO.getPreConnect() == null || endPlanBO.getSufNodeConnect() == null) {
            //无前置任务
            return null;
        }

        TaskDB preTask = new TaskDB();
        preTask.setStartNode(taskDB.selectStartNode());
        preTask.setEndNode(endPlanBO.getPreConnect());
        preTask.setTaskType(taskDB.getTaskType());
        preTask.setTaskPortId(taskDB.getConnectPortCode());
        preTask.setPriorityCode(taskDB.getPriorityCode());
        preTask.setBarCode(taskDB.getBarCode());
        preTask.setWmsTaskId(null);
        preTask.setTaskPortId(endPlanBO.getConnectPortCode());

        taskDBService.insertTask(Collections.singletonList(preTask));
        taskDB.setPreTaskId(preTask.getTaskId());

        return endPlanBO.getSufNodeConnect();
    }

    /**
     * 设置出库任务终点
     * @param taskDB
     * @param endNode
     * @param portDB
     * @param startNode
     */
    private void improveTask(TaskDB taskDB, NodeDB endNode, PortDB portDB, Node startNode) {
        taskDB.setEndNode(new Node(endNode.getGridx(), endNode.getGridy(), endNode.getGridz()));
        taskDB.setTaskPortId(portDB.getPortCode());
        if (startNode == null) {
            taskDB.setAllowAssignmentRgv(true);
        } else {
            taskDB.setAllowAssignmentRgv(false);
            taskDB.setStartNode(startNode);
        }

        taskDBService.setGroupAndZone(taskDB);
        taskDBService.updateById(taskDB);
        LoggerUtil.info("完善出库任务终点:" + taskDB, this.getClass());
    }
}
